﻿using System;
using System.Net;
using System.Net.Sockets;

using LoginServer.Manager;
using LoginServer.Networking;
using LoginServer.Networking.Packets;

namespace LoginServer.Virtual_Objects.User
{
    class virtualUser
    {
        public int UserID;
        public string Nickname;
        public string Username;
        public string Password;
        public int SessionID;
        public int AccessLevel = 0;

        public virtualUser(Socket uSocket)
        {
            this.uSocket = uSocket;

            send(new PACKET_CONNECT());
            //DB.runQuery("INSERT INTO log_connections (`timestamp`, `server`, `status`, `ip`, `host`) VALUES ('" + Program.UnixTimestamp + "', '0', '0', '" + this.IPAddress + "', '" + this.Hostname + "');");

            uSocket.BeginReceive(dataBuffer, 0, dataBuffer.Length, SocketFlags.None, new AsyncCallback(arrivedData), null);
        }

        ~virtualUser()
        {
            GC.Collect();
        }

        #region Networking

        private Socket uSocket;
        private byte[] dataBuffer = new byte[1024];
        private bool isDisconnected = false;

        #region Arrival

        private void arrivedData(IAsyncResult iAr)
        {
            try
            {
                int DataLength = uSocket.EndReceive(iAr);

                if (DataLength > 1)
                {
                    byte[] packetBuffer = new byte[DataLength];
                    Array.Copy(dataBuffer, 0, packetBuffer, 0, DataLength);

                    /* Decode Packet */
                    for (int I = 0; I < packetBuffer.Length; I++)
                    {
                        packetBuffer[I] = (byte)(packetBuffer[I] ^ 0xC3);
                    }

                    PacketHandler pHandler = PacketManager.parsePacket(packetBuffer);

                    if (pHandler != null)
                    {
                        pHandler.Handle(this);
                    }

                    uSocket.BeginReceive(dataBuffer, 0, dataBuffer.Length, SocketFlags.None, new AsyncCallback(arrivedData), null);
                }
                else
                {
                    disconnect();
                }
            }
            catch { disconnect(); }
        }

        #endregion

        #region Send

        public void send(Packet p)
        {
            byte[] sendBuffer = p.getBytes();
            try { uSocket.BeginSend(sendBuffer, 0, sendBuffer.Length, SocketFlags.None, new AsyncCallback(sendCallBack), null); }
            catch { disconnect(); }
        }

        private void sendCallBack(IAsyncResult iAr)
        {
            try { uSocket.EndSend(iAr); }
            catch { disconnect(); }
        }

        #endregion

        #region Disconnect
        public void disconnect()
        {
            if (isDisconnected) return;
            isDisconnected = true;

            Log.WriteLine("IP : " + IPAddress + " is disconnected");
            //DB.runQuery("INSERT INTO log_connections (`timestamp`, `server`, `status`, `ip`, `host`) VALUES ('" + Program.UnixTimestamp + "', '0', '1', '" + IPAddress + "', '" + Hostname + "');");

            try { uSocket.Close(); }
            catch { }
        }
        #endregion

        public String IPAddress { get { return uSocket.RemoteEndPoint.ToString().Split(':')[0]; } }
        public String Hostname { get { return Dns.GetHostEntry(this.IPAddress).HostName; } }
        #endregion
    }
}
